package com.sky.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.sky.annotation.CleanRedis;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.exception.BaseException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.Mapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
@Transactional
public class DishServiceImpl implements DishService {
    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Autowired
    private RedisTemplate redisTemplate;
    private String key = "sky:admin:dishes";

    @Override
    public PageResult getPage(DishPageQueryDTO dishPageQueryDTO) {

        //实现分页
        List<DishVO> list = null;

        //redis-1 判断redis里面有没有数据
        if (redisTemplate.hasKey(key)) {
            log.info("直接从redis读取数据");
            //redis-2.有，直接读出
            String jsonStr = (String) redisTemplate.opsForValue().get(key);
            list = JSONUtil.toList(jsonStr, DishVO.class);
        } else {
            //redis-3.没有，查数据库，然后存一份到redis，以后就可以不查数据库了
            //0.取得所有的记录
            log.info("查数据库获取数据");
            list = dishMapper.getList();
            String jsonStr = JSONUtil.toJsonStr(list);
            log.info(jsonStr);
            //todo key编排方式：工程名+模块名+业务场景名[+特征码]
            redisTemplate.opsForValue().set("sky:admin:dishes", jsonStr);
        }

        //1.取得符合条件的所有记录 （大数组）-> 总记录条数
        Stream<DishVO> stream = list.stream();
        if (StrUtil.isNotBlank(dishPageQueryDTO.getName())) {
            stream = stream.filter(s -> s.getName().contains(dishPageQueryDTO.getName()));
        }

        if (dishPageQueryDTO.getCategoryId() != null) {
            stream = stream.filter(s -> s.getCategoryId() == Long.parseLong(String.valueOf(dishPageQueryDTO.getCategoryId())));
        }

        if (dishPageQueryDTO.getStatus() != null) {
            stream = stream.filter(s -> s.getStatus().equals(dishPageQueryDTO.getStatus()));
        }

        List<DishVO> collect = stream.collect(Collectors.toList());
        long count = collect.size();

        //2.取得当前页需要显示的记录 （小数组) -> 填充当前页面
        List<DishVO> dishList = collect.stream()
                .skip((dishPageQueryDTO.getPage() - 1) * dishPageQueryDTO.getPageSize())
                .limit(dishPageQueryDTO.getPageSize())
                .collect(Collectors.toList());

        PageResult pageResult = new PageResult();
        pageResult.setRecords(dishList);
        pageResult.setTotal(count);
        return pageResult;
    }


    @Override
    @CleanRedis("sky:admin:dishes")
    public void saveWithFlavor(DishDTO dishDTO) {
        //todo 需要写入两张表，这种情况需要加事务
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        log.info("{}", dish);
        dishMapper.add(dish);
        log.info("{}", dish);
        log.info("新记录的id是：{}", dish.getId());

        List<DishFlavor> flavors = dishDTO.getFlavors();
        //todo 这里需要把新的菜品记录的id返回给口味 -> 新插入的数据怎么获取id？
        for (DishFlavor flavor : flavors) {
            flavor.setDishId(dish.getId());
            log.info("{}", flavor);
            dishFlavorMapper.add(flavor);
        }
    }

    @Override
    @CleanRedis("sky:admin:dishes")
    public void deleteBatch(List<Long> ids) {
        //todo 一次操作多条记录时需要考虑事务
        for (Long id : ids) {
            //通过id获取菜品数据，检查是否在售
            Dish dish = dishMapper.getById(id);
            if (dish.getStatus() == 1) {
                throw new BaseException("在售的菜品不能删除");
            }
            //todo 将来这个位置来判断套餐
            dishMapper.deleteById(id);
            //todo 删除商品对应的口味
        }

        //todo Redis数据库也需要清空
        //redisTemplate.delete(key);
    }

    @Override
    public DishVO getById(Long id) {
        DishVO dishVO = new DishVO();
        // Dish -> DishVO
        Dish dish = dishMapper.getById(id);
        BeanUtils.copyProperties(dish, dishVO);
        //DishFlavor->DishVO
        List<DishFlavor> dishFlavors = dishFlavorMapper.getByDishId(id);
        dishVO.setFlavors(dishFlavors);
        return dishVO;
    }

    @Override
    @CleanRedis("sky:admin:dishes")
    public void updateWithFlavor(DishDTO dishDTO) {
        //1.更新菜品
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        dishMapper.update(dish);
        //2.更新口味
        //思路：先把老的口味全删掉，用传入的数据，重建口味记录
        dishFlavorMapper.deleteByDishId(dishDTO.getId());
        List<DishFlavor> newDishFlavor = dishDTO.getFlavors();
        for (DishFlavor dishFlavor : newDishFlavor) {
            log.info("口味：{}", dishFlavor);
            //todo 这个位置为了防止口味是新增的会抛异常，补一个dishId
            dishFlavor.setDishId(dishDTO.getId());
            dishFlavorMapper.add(dishFlavor);
        }

    }

    @Override
    public void setStatus(Dish dish) {
        dishMapper.setStatus(dish);
    }

    @Override
    public List<Dish> getDishListByCategoryId(Long categoryId) {
        List<Dish> list = dishMapper.getDishListByCategoryId(categoryId);
        return list;
    }

}
